<?php

/**
 * @copyright Michiel Hakvoort 2010
 * @license http://www.opensource.org/licenses/bsd-license.php New BSD
 * @package mangrove
 * @subpackage core
 * @filesource
 */

/*
 * Copyright (c) 2010 Michiel Hakvoort
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

namespace mg;

interface PhpModifiers {

    const IS_FINAL = 0x01;
    const IS_PUBLIC = 0x02;
    const IS_PRIVATE = 0x04;
    const IS_PROTECTED = 0x08;
    const IS_ABSTRACT = 0x10;
    const IS_STATIC = 0x20;
    const IS_INTERFACE = 0x40;

}

/**
 * A static offline definition of a class
 *
 * @author Michiel Hakvoort <michiel@hakvoort.it>
 *
 */
class ClassHeader implements PhpModifiers {

    private $qualifiedName;
    private $modifiers;
    private $file = null;
    private $interfaces = null;

    private $methods = null;
    private $qualifiedNameParent = null;
    private $constants = null;

    public function __construct($qualifiedName, $modifiers, $file = null) {
        $this->qualifiedName = mb_strtolower($qualifiedName);
        $this->modifiers = $modifiers;
        $this->file = $file;
        $this->interfaces = array();
        $this->methods = array();
        $this->constants = array();
    }

    public function getConstants() {
        return $this->constants;
    }

    public function setParentClass($qualifiedNameParent) {
        $this->qualifiedNameParent = mb_strtolower($qualifiedNameParent);
    }

    public function getParentClass() {
        return $this->qualifiedNameParent;
    }

    public function getParents() {
        $result = $this->getInterfaces();

        if($this->qualifiedNameParent !== null) {
            $result[] = $this->qualifiedNameParent;
        }

        return $result;
    }

    public function addInterface($qualifiedNameInterface) {
        $this->interfaces[] = mb_strtolower($qualifiedNameInterface);
    }

    public function getInterfaces() {
        return $this->interfaces;
    }

    public function addMethod(MethodHeader $methodHeader) {
        $this->methods[] = $methodHeader;
    }

    public function getMethods() {
        return $this->methods;
    }

    public function setConstant($name, $value) {
        $this->constants[$name] = trim($value);
    }

    public function getName() {
        if(($index = mb_strrpos($this->qualifiedName, '\\')) !== false) {
            return mb_substr($this->qualifiedName, $index + 1);
        }
        return $this->qualifiedName;
    }

    public function getQualifiedName() {
        return $this->qualifiedName;
    }

    public function getNamespace() {
        if(($index = mb_strrpos($this->qualifiedName, '\\')) !== false) {
            return mb_substr($this->qualifiedName, 0, $index);
        }

        return '';
    }

    public function getModifiers() {
        return $this->modifiers;
    }

    public function isFinal() {
        return ($this->modifiers & self :: IS_FINAL) !== 0;
    }

    public function isAbstract() {
        return ($this->modifiers & self :: IS_ABSTRACT) !== 0;
    }

    public function isInterface() {
        return ($this->modifiers & self :: IS_INTERFACE) !== 0;
    }

    public function isInternal() {
        return $this->file === null;
    }

    public function getFile() {
        return $this->file;
    }
}

/**
 * A static offline definition of a method
 *
 * @author Michiel Hakvoort
 *
 */
class MethodHeader implements PhpModifiers {

    private $name = null;
    private $modifiers = null;

    public function __construct($name, $modifiers) {
        $this->name = mb_strtolower($name);
        $this->modifiers = $modifiers;
    }

    public function getName() {
        return $this->name;
    }

    public function getModifiers() {
        return $this->modifiers;
    }

    public function __toString() {
        return $this->name;
    }
}

